/**
 * @desc 页面管理
 * @author: FFFF
 */
import { ref, reactive, getCurrentInstance } from 'vue'
import { defaultOptions } from "./common/config/defaultOptions.js";
import { generateDataJson } from './common/config/generateData.js';
import { cloneObject, randomNumber } from './common/util/util.js'
import { message } from 'ant-design-vue'
import { initComponents } from './componentManager.js'
import { revoke } from './common/util/revoke.js';

// 页面模板数据
const generateDataString = JSON.stringify(generateDataJson);
export const generateData = reactive(JSON.parse(generateDataString));

// 所有组件的事件
export const componentEvents = reactive([]);

// 页面数据源
export let pageData = reactive({});

// 自定义函数列表
export let funcs = ref([{ active: false, name: "test", method: {} }]);

export let globalOptions = reactive({});

// 中转数据
export const storage = reactive({
    selectItem: undefined,
    pageType: globalOptions.selectPageType,
    jsonViewOpen: false, // 源码弹窗打开状态
    resizeTrigger: false, // 组件拖拽大小状态
    scriptEditorError: false, // 脚本编辑器错误状态
})

export const formStorage = reactive({
    // form: null
})

/**
 * 初始化页面设计器
 */
export const initDesigner = (options) => {

    if (options) {
        globalOptions = { ...defaultOptions, ...options };
    } else {
        globalOptions = defaultOptions;
    }

    generateData.data = fixGenerateData(generateData.data);
    revoke.add(generateData.data, '初始化')
    initComponents();
}

/**
 * 初始化建造器
 * @param {Object} pageTemplate 页面json模板
 * @param {Object} data 页面数据
 */
export function initBuilder(pageTemplate, data) {
    generateData.data = pageTemplate.data;
    // pageData = data;
    // 初始化组件
    initComponents();
    setDynamicsMethods(pageTemplate.script);
}

/**
 * @method
 * @desc 获取唯一索引
 */
export const getPrimaryId = () => {
    // let componentsData = generateData.data.children;
    // let allComponents = getAllComponents(componentsData);
    return "0" + randomNumber(4);
}

/**
 * @method
 * @param {*} componentsData 
 * @returns {Array} 界面已加载的所有组件
 */
const getAllComponents = (componentsData) => {
    let allComponents = [];
    for (let i = 0; i < componentsData.length; i++) {
        let item = componentsData[i];
        allComponents.push(item);
        if (item.children != undefined && item.children.length > 0) {
            allComponents.push(...getAllComponents(item.children));
        }
    }
    return allComponents;
}

/**
 * @method
 * @param {Object} exposed 函数列表对象
 * @desc 暴露函数给funcs
 */
export const dcDefineExpose = (exposed) => {
    funcs.value = [];
    for (let val in exposed) {
        if (typeof exposed[val] == 'function') {
            funcs.value.push({
                active: false,
                name: val,
                method: exposed[val]
            })
        }
    }
}


/**
 * @method
 * @param {String} id 如不传则获取全部组件
 * @desc 通过组件ID获取组件
 */
export const getComponents = (id) => {

    // console.log("需要获取组件的Id：", id);

    let allComponents = generateData.data.children;
    if (id != undefined) {   // 获取指定ID的组件
        const findItem = (arr, id) => {
            let returnItem = null;
            for (let i = 0; i < arr.length; i++) {
                let item = arr[i];
                if (item.id == id) {
                    returnItem = item;
                    return returnItem;
                }
                if (item.children != undefined && item.children.length > 0) {
                    returnItem = findItem(item.children, id);
                    return returnItem;
                }
            }
        }

        // 返回需要的组件
        let item = findItem(allComponents, id);

        if (item) {
            let comp = {
                component: item,
                setValue: function (value) {
                    setComponentValue(this.component, value)
                },
                getValue: function (key) {
                    return getComponentValue(this.component);
                }
            }

            if (item.type == 'form') {
                comp.form = formStorage[item.id]
            }
            return comp
        } else {
            // console.log(`未查找到【id：${id}】对应的组件`);
            // message.warning(`未查找到【id：${id}】对应的组件`)
        }
    } else {  // 未传ID，获取全部组件
        return allComponents
    }
}

/**
 * @method
 * @param {Object} item 组件对象
 * @param {Object} value 组件值
 * @desc 设置组件的值
 */
const setComponentValue = function (item, value) {
    pageData[item.field] = value;
}

/**
 * @method
 * @param {Object} item 组件对象
 * @desc 设置组件的值
 */
const getComponentValue = function (item) {
    return pageData[item.field]
}

/**
 * @method
 * @description 设置动态函数
 */
export const setDynamicsMethods = (scriptStr, callback) => {
    let success = true;
    try {
        new Function('value', scriptStr).bind({
            dcDefineExpose,
            getComponents,
            pageData
        })();
        storage.scriptEditorError = false;
        success = true;
    } catch (err) {
        storage.scriptEditorError = true;
        success = false;
    } finally {
        if (typeof callback == 'function') {
            callback(success);
        }
    }
}

/**
 * @method
 * @param {Object} item 当前组件
 * @param {String} eventType 事件类型
 * @desc 获取组件的自定义函数事件
 */
export const getCustomMethod = (item, eventType, e) => {
    let methodObj = {};   // 存放需要执行的自定义函数
    // 定义返回的函数对象
    let returnFunc = (methodObj) => {
        if (methodObj != undefined) {
            // 循环执行自定义函数
            for (let item in methodObj) {
                if (typeof methodObj[item] == 'function') {
                    methodObj[item](e);
                }
            }
        }
    };
    // 如果当前组件的event事件已定义
    if (item.event != undefined) {
        let eventList = item.event[eventType];
        // event事件中对应类型的函数列表已存在
        if (eventList != undefined) {
            for (let i = 0; i < eventList.length; i++) {
                let event = eventList[i];
                methodObj[event.methodName] = getFuncsValueMethod(event.methodName);
            }
        }
    }
    return returnFunc(methodObj)
}

/**
 * @method
 * @param {String} methodName 方法名称
 * @desc 获取自定义函数列表的函数体
 */
const getFuncsValueMethod = (methodName) => {
    for (let i = 0; i < funcs.value.length; i++) {
        let funcsItem = funcs.value[i];
        if (funcsItem.name == methodName) {
            return funcsItem.method
        }
    }
}

/**
 * @method
 * @param {String}  methodName 函数名
 * @desc 获取已经绑定该函数的组件
 */
export const getBoundThisMehodComponent = (methodName) => {
    // console.log("当前数据：",generateData)
    // 当前界面上的所有组件
    let allComponents = generateData.data.children
    let boundComponents = filterComponents(allComponents, methodName);
    let boundPages = filterPages(methodName);
    // console.log("已经绑定了该函数的组件：", boundComponents)

    return [...boundComponents, ...boundPages];
}

// 在页面数据中查绑定了该函数的事件
const filterPages = (methodName) => {
    let boundPages = [];
    let pages = generateData.data;
    if (pages.event != undefined) {
        for (let val in pages.event) {
            let eventList = pages.event[val];
            for (let j = 0; j < eventList.length; j++) {
                let event = eventList[j];
                if (event.methodName == methodName) {
                    boundPages.push({
                        component: pages,
                        eventName: val,
                        eventDesc: event.name
                    })
                }
            }
        }
    }
    return boundPages;
}


// 查找已绑定该函数的组件
const filterComponents = (allComponents, methodName) => {
    let boundComponents = [];

    for (let i = 0; i < allComponents.length; i++) {
        let item = allComponents[i];
        if (item.event != undefined) {
            for (let val in item.event) {
                let eventList = item.event[val];
                for (let j = 0; j < eventList.length; j++) {
                    let event = eventList[j];
                    if (event.methodName == methodName) {
                        boundComponents.push({
                            component: item,
                            eventName: val,
                            eventDesc: event.name
                        })
                    }
                }
            }
        }

        // 如果存在子组件
        if (item.children != undefined && item.children.length > 0) {
            boundComponents = boundComponents.concat(filterComponents(item.children, methodName))
        }
    }

    return boundComponents;
}

/**
 * 设置导入的数据
 * @param {Object} jsonData 
 * @param {Function} callback 
 */
export const setImportJsonData = (jsonData, callback) => {

    generateData.data = jsonData.data;
    setDynamicsMethods(jsonData.script);
    if (typeof callback == 'function') callback();
}

export function hasChildren(jsonObj) {
    return jsonObj.children != undefined
}

/**
 * 清理数据结构
 */
export function fixGenerateData(data) {

    let copyData = JSON.parse(JSON.stringify(data));

    // delete copyData.id;
    delete copyData.icon;

    copyData.children = eachFixData(copyData.children);
    return copyData;
}

/**
 * 遍历修改数据结构
 */
const eachFixData = (data) => {
    let resultData = JSON.parse(JSON.stringify(data));

    for (let i = 0; i < resultData.length; i++) {
        let item = resultData[i];

        // delete item.id;
        delete item.icon;
        delete item.name;
        // delete item.active;
        delete item.optionName;
        delete item.groupName;
        delete item.isShow;
        delete item.notUseDefaultStyle;

        if (item.children) {
            item.children = eachFixData(item.children);
        }
    }
    return resultData;
}

/**
 * 手动设置页面模板数据
 * @param {Object} data 
 */
export const manualSetPageTemplate = (data) => {
    setImportJsonData(cloneObject(data), () => {
        message.success("页面模板数据设置成功")
    })
}

/**
 * 获取页面模板数据
 * @returns 页面模板数据
 */
export const getPageTepl = () => {
    return generateData
}

/**
 * @method
 * @desc 重置画布
 */
export const resetPagePanel = () => {
    generateData.data.children = [];
    storage.selectItem = undefined;
}

/**
 * @method
 * @desc 设置页面类型
 */
export const setPageTypeSelect = (type) => {
    storage.pageType = type;
}


/**
 * 校验表单，如果传入id，则校验指定表单，否则校验所有表单
 * @param {*} id  
 */
export const validateFormData = (id) => {

    if (id) {
        formStorage[id].validate();
    } else {
        for (let key in formStorage) {
            let form = formStorage[key]
            form.validate()
        }
    }
}

// 设置页面数据
export const setPageData = (data) => {
    clearPageData();
    for (let key in data) {
        pageData[key] = data[key];
    }
}

// 清空页面数据
export const clearPageData = () => {
    for (const key in pageData) {
        if (pageData.hasOwnProperty(key)) {
            delete pageData[key];
        }
    }
}

// 获取页面数据
export const getPageData = () => {
    return pageData;
}

// 获取页面组件
export const getPageComponents = (id) => {
    let comp = getComponents(id);
    if (comp) {
        return comp.component;
    }
}

/**
 * @method
 * @param {String} field 字段名
 * @param {any} value 值
 * @desc 给指定字段设置数据
 */
export const setPageFieldData = (field, value) => {
    pageData[field] = value;
}

/**
 * 手动给组件赋值,多个组件赋值传入数组对象，单个组件则传入对象
 */
export const setPageComponentValue = (data) => {
    if (Array.isArray(data)) {
        for (let i = 0; i < data.length; i++) {
            let obj = data[i];
            setCompValue(obj);
        }
    } else {
        setCompValue(data);
    }
}
const setCompValue = (obj) => {
    let comp = getPageComponents(obj.id);
    let field = comp.field;
    pageData[field] = obj.value;
}


/**
 * 手动给组件属性设置值,多个组件赋值传入数组对象，单个组件则传入对象	
 */
export const setPageComponentProps = (data) => {
    if (Array.isArray(data)) {
        for (let i = 0; i < data.length; i++) {
            let obj = data[i];
            setCompProps(obj);
        }
    } else {
        setCompProps(data);
    }
}
const setCompProps = (obj) => {
    let comp = getPageComponents(obj.id);
    if (comp.componentProps.hasOwnProperty(obj.propName)) {
        comp.componentProps[obj.propName] = obj.propValue;
    }
}